//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Server.h"
#include "Ws2tcpip.h"
//---------------------------------------------------------------------------
#pragma link "Ws2_32.lib"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------

#define DEFAULT_BUFLEN 1024*1024
#define DEFAULT_PORT "27015"

void __fastcall TListenThrd::Execute()
{
	int iResult;
	char *recvbuf = new char(DEFAULT_BUFLEN);
	int recvbuflen = DEFAULT_BUFLEN;

    // Accept a client socket
    fClientSocket = accept(fListenSocket, NULL, NULL);
    if (fClientSocket == INVALID_SOCKET) {
        closesocket(fListenSocket);
        WSACleanup();
        return ;
    }
	// No longer need server socket
	closesocket(fListenSocket);

    // Receive until the peer shuts down the connection
    do {
        iResult = recv(fClientSocket, recvbuf, recvbuflen, 0);
		if (iResult > 0)
        	fServer->onRecv(recvbuf);
        else if (iResult < 0){
			closesocket(fClientSocket);
			WSACleanup();
            return ;
		}
    } while (iResult > 0);
	/*
    // Echo the buffer back to the sender
    iResult = send(ClientSocket, recvbuf, iResult, 0 );
    if (iResult == SOCKET_ERROR) {
		retStr.sprintf(L"send failed: %d\n", WSAGetLastError());
		Memo1->Lines->Add(retStr);
        closesocket(ClientSocket);
        WSACleanup();
        return ;
    }
    retStr.sprintf(L"Bytes Sent: %ld\n", iResult);
	Memo1->Lines->Add(retStr);
    // shutdown the connection since we're done
    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
		retStr.sprintf(L"shutdown failed: %d\n", WSAGetLastError());
		Memo1->Lines->Add(retStr);
        closesocket(ClientSocket);
        WSACleanup();
        return ;
    }
	// cleanup
	closesocket(ClientSocket);
	WSACleanup();
	*/
}

__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	// Initialize Winsock
	int retVal;
	fClientSocket = INVALID_SOCKET;
	fListenSocket = INVALID_SOCKET;

    Memo1->Lines->Clear();
	retVal = WSAStartup(MAKEWORD(2,2), &fWSAData);
	assert(retVal == 0);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{

	int iResult;
	ADDRINFOA hints;
	UnicodeString retStr;
	char* ip = "127.0.0.1";
	ADDRINFOA *result = NULL;

	ZeroMemory(&hints, sizeof(ADDRINFOA));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;




	UnicodeString ipStr;
    char   szHostname[100];
	HOSTENT   *pHostEnt;
	in_addr   inAddr;

	gethostname(szHostname,   sizeof(szHostname));
	pHostEnt = gethostbyname(szHostname);
	memcpy(&inAddr.S_un,   pHostEnt->h_addr,   pHostEnt->h_length);
	ipStr = inet_ntoa(inAddr);

	// Resolve the server address and port
	iResult = getaddrinfo(AnsiString(ipStr).c_str(), DEFAULT_PORT, &hints, &result);
	if (iResult != 0) {
		retStr.sprintf(L"getaddrinfo failed: %d", iResult);
        Memo1->Lines->Add(retStr);
		WSACleanup();
		return ;
	}

	fListenSocket = socket(result->ai_family, result->ai_socktype,result->ai_protocol);
	if (fListenSocket == INVALID_SOCKET) {
		retStr.sprintf(L"Error at socket(): %ld", WSAGetLastError());
		Memo1->Lines->Add(retStr);
		freeaddrinfo(result);
		WSACleanup();
		return;
	}

    iResult = bind(fListenSocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
		retStr.sprintf(L"bind failed: %d\n", WSAGetLastError());
		Memo1->Lines->Add(retStr);
        freeaddrinfo(result);
        closesocket(fListenSocket);
        WSACleanup();
        return ;
    }

    freeaddrinfo(result);

	iResult = listen(fListenSocket, SOMAXCONN);
	if (iResult == SOCKET_ERROR) {
		retStr.sprintf(L"listen failed: %d\n", WSAGetLastError());
		Memo1->Lines->Add(retStr);
		closesocket(fListenSocket);
		WSACleanup();
		return ;
	}
	fListenThrd = new TListenThrd(fListenSocket, false, (ISocket*)this);
}
//---------------------------------------------------------------------------

void TForm1::onRecv(UnicodeString data)
{
	Memo1->Lines->Add(data);
}
